package com.intelij.adapter.actions;

import com.intelij.adapter.ConversionService;
import com.intelij.adapter.eums.ClassType;
import com.intelij.adapter.eums.Message;
import com.intelij.adapter.eums.SourceType;
import com.intelij.adapter.eums.TargetType;
import com.intelij.adapter.source.Source;
import com.intelij.adapter.source.UmlSupportSource;
import com.intelij.adapter.target.Target;
import com.intelij.adapter.util.Md5Utils;
import com.intelij.adapter.util.UmlSupportUtils;
import com.intellij.diagram.DiagramBuilder;
import com.intellij.diagram.DiagramDataKeys;
import com.intellij.diagram.DiagramNode;
import com.intellij.diagram.presentation.DiagramState;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.fileChooser.FileSaverDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.psi.PsiElement;
import com.intellij.uml.UmlVirtualFileSystem;
import com.intellij.uml.java.JavaUmlDataModel;
import org.apache.commons.lang3.StringUtils;
import org.jdom.Element;

import java.io.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

/**
 * 适配事件类
 */
public class UmlAdapterAction extends AnAction {
    public static Map<String, ClassType> nodeTypeMap = new HashMap<>();

    @Override
    public void actionPerformed(AnActionEvent e) {
        if (UmlSupportUtils.isUmlSupport(e)) {
            //初始化节点类型，注意需要放在保存弹窗弹出之前
            initNodeTypeMap(e);
            DiagramState state = UmlSupportUtils.getDiagramStateByEvent(e);
            Element element = new Element("temp");
            state.write(element);
            Project project = e.getProject();
            VirtualFile vf = UmlSupportUtils.getUmlVirtualFileByEvent(e);
            //弹窗选择保存路径和转换目标类型
            VirtualFileWrapper wrapper = FileChooserFactory.getInstance()
                    .createSaveFileDialog(new FileSaverDescriptor(Message.SAVE_CONVERT_FILE.getContext(), Message.SAVE_CONVERT_FILE.getTitle(), new String[]{TargetType.PROCESS_ON.getExtName()}), project)
                    .save(project.getBaseDir(), ((UmlVirtualFileSystem.UmlVirtualFile) vf).getShortName());
            try {
                //执行转换操作
                convertAndSave(element, wrapper.getFile());
            } catch (Exception ex) {
                Messages.showMessageDialog(project, Message.FILE_SAVE_EXCEPTION.getTitle(), Message.FILE_SAVE_EXCEPTION.getContext(), Messages.getInformationIcon());
            }
        } else {
            Project project = e.getData(PlatformDataKeys.PROJECT);
            Messages.showMessageDialog(project, Message.NOT_UML_SUPPORT.getTitle(), Message.NOT_UML_SUPPORT.getContext(), Messages.getInformationIcon());
        }
    }

    private void convertAndSave(Element element, File file) {
        try {
            Source source = new UmlSupportSource(element);
            Target target = ConversionService.convert(source, SourceType.UML_SUPPORT, StringUtils.substringAfterLast(file.getName(), "."));
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                br = new BufferedReader(new InputStreamReader(target.getTargetStream()));
                bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file)));
                String temp;
                while ((temp = br.readLine()) != null) {
                    bw.write(temp);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (br != null) {
                    br.close();
                }
                if (bw != null) {
                    bw.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initNodeTypeMap(AnActionEvent e) {
        DiagramBuilder builder = DiagramDataKeys.BUILDER.getData(e.getDataContext());
        JavaUmlDataModel model = (JavaUmlDataModel) builder.getDataModel();
        Collection<DiagramNode<PsiElement>> nodes = model.getNodes();
        nodes.stream().forEach(f -> {
            String name = f.toString().replaceAll("<html>|<b>|</b>|</html>", "");
            nodeTypeMap.put(Md5Utils.generateMd5(name.getBytes()), getNodeType(f.getIcon().toString()));
        });
    }

    private ClassType getNodeType(String url) {
        ClassType type = ClassType.CLASS;
        if (url.indexOf("interface.png") > 0) {
            type = ClassType.INTERFACE;
        } else if (url.indexOf("abstractClass.png") > 0) {
            type = ClassType.ABSTRACT;
        } else if (url.indexOf("annotationtype.png") > 0) {
            type = ClassType.ANNOTATIONTYPE;
        }
        return type;
    }
}
